package cn.xiaopengstack.infrastructure.gateway.adapter;

import cn.xiaopengstack.domain.weixin.auth.adapter.ILoginPort;
import cn.xiaopengstack.domain.weixin.auth.model.valobj.IpInfoVO;
import cn.xiaopengstack.infrastructure.gateway.IWeixinApiService;
import cn.xiaopengstack.infrastructure.gateway.IpHelper;
import cn.xiaopengstack.infrastructure.gateway.dto.WeixinQrCodeRequestDTO;
import cn.xiaopengstack.infrastructure.gateway.dto.WeixinQrCodeResponseDTO;
import cn.xiaopengstack.infrastructure.gateway.dto.WeixinTemplateMessageDTO;
import cn.xiaopengstack.infrastructure.gateway.dto.WeixinTokenResponseDTO;
import com.google.common.cache.Cache;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import retrofit2.Call;

import javax.annotation.Resource;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * @author jiangyangang
 */
@Service
@Slf4j
public class LoginPort implements ILoginPort {

    @Value("${weixin.config.app-id}")
    private String appid;
    @Value("${weixin.config.app-secret}")
    private String appSecret;
    @Value("${weixin.config.template_id}")
    private String template_id;

    @Resource
    private IWeixinApiService weixinApiService;

    @Resource
    private Cache<String, String> weixinAccessTokenCache;

    @Resource
    private IpHelper ipHelper;


    private static final String CACHE_WEIXIN_ACCESS_TOKEN = "weixin.auth.accessToken.%s";

    @Override
    public String createQrCodeTicket() throws IOException {
        String accessToken = getAccessToken();

        // 生成ticket
        WeixinQrCodeRequestDTO requestDTO = WeixinQrCodeRequestDTO.builder()
                .action_info(WeixinQrCodeRequestDTO.ActionInfo.builder()
                        .scene(WeixinQrCodeRequestDTO.ActionInfo.Scene.builder()
                                .scene_id(100601)
                                .build())
                        .build())
                .action_name(WeixinQrCodeRequestDTO.ActionNameTypeVO.QR_SCENE.getCode())
                .expire_seconds(2592000)
                .build();
        Call<WeixinQrCodeResponseDTO> qrCodeCall = weixinApiService.createQrCode(accessToken, requestDTO);
        WeixinQrCodeResponseDTO qrCodeResponseDTO = qrCodeCall.execute().body();
        assert qrCodeResponseDTO != null;

        return qrCodeResponseDTO.getTicket();
    }

    @NotNull
    private String getAccessToken() throws IOException {
        String cacheKey = String.format(CACHE_WEIXIN_ACCESS_TOKEN, appid);
        // 获取accessToken
        String accessToken = weixinAccessTokenCache.getIfPresent(cacheKey);
        if (Objects.isNull(accessToken)) {
            Call<WeixinTokenResponseDTO> accessTokenResp = weixinApiService.getToken("client_credential", appid, appSecret);
            WeixinTokenResponseDTO accessTokenDTO = accessTokenResp.execute().body();
            assert accessTokenDTO != null;
            accessToken = accessTokenDTO.getAccess_token();
            weixinAccessTokenCache.put(String.format(CACHE_WEIXIN_ACCESS_TOKEN, appid), accessToken);
        }
        return accessToken;
    }

    @Override
    public void sendLoginTemplate(String openid) throws IOException {
        // 获取accessToken
        String accessToken = getAccessToken();

        // 不能这个获取IP
        Optional<IpInfoVO> ipInfoOpt = Optional.of(ipHelper.getIpInfo());

        HashMap<String, Map<String, String>> data = new HashMap<>();
        String nowTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        WeixinTemplateMessageDTO.put(data, WeixinTemplateMessageDTO.TemplateKey.USER, openid);
        WeixinTemplateMessageDTO.put(data, WeixinTemplateMessageDTO.TemplateKey.LOGIN_TIME, nowTime);
        WeixinTemplateMessageDTO.put(data, WeixinTemplateMessageDTO.TemplateKey.LOGIN_IP, ipInfoOpt.map(IpInfoVO::getQuery).orElse("未知"));
        WeixinTemplateMessageDTO.put(data, WeixinTemplateMessageDTO.TemplateKey.LOGIN_AREA, ipInfoOpt.map(IpInfoVO::getCountry).orElse("未知") + " " + ipInfoOpt.map(IpInfoVO::getCity).orElse("未知"));

        WeixinTemplateMessageDTO templateMessageDTO = new WeixinTemplateMessageDTO(openid, template_id);
        templateMessageDTO.setUrl("https://dapeng8848");
        templateMessageDTO.setData(data);

        Call<Void> sendMessageCall = weixinApiService.sendMessage(accessToken, templateMessageDTO);
        sendMessageCall.execute();
    }
}
